package com.simon.study.algorithm.collect;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *
 * @author SimonLiu
 * @date 2022/8/30 22:19
 */
public class LocalLRUCacheDup<K,V> {
    private int size;

    private int capacity;


    public class Node{
        Node prev;
        Node next;

        K key;
        V value;

        public Node() {
        }

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }


    private Node head = new Node();
    private Node tail = new Node();

    private Map<K, Node> map = new HashMap<>();

    public LocalLRUCacheDup(int capacity) {
        this.capacity   = capacity;
        this.head.next  = this.tail;
        this.tail.prev  = this.head;
        this.size       = 0;
    }


    public V get(K key){
        Node tar = map.get(key);
        if(tar == null){ return null; }
        moveToHead(tar);
        return tar.value;
    }


    public void put(K key, V value){
        Node tar = map.get(key);
        if(tar == null){
            Node newNode = new Node(key, value);
            map.put(key, newNode);
            addToHead(newNode);
            size++;
            if(size > capacity){ removeTail(); }
        }else{
            tar.value = value;
            moveToHead(tar);
        }
    }

    private void removeNode(Node node){
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private void removeTail(){
        Node lastNode = tail.prev;
        removeNode(lastNode);
        size--;
    }


    private void addToHead(Node node){
        node.next = head.next;
        head.next = node;
        node.next.prev = node;
        node.prev = head;
    }

    private void moveToHead(Node node){
        removeNode(node);
        addToHead(node);
    }
}
